package cn.com.zp.util.base;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

public class FileUtils {
	public enum FileState {
		isExists, isNotExists, isEmpty, isNotEmpty,
	}

	/**
	 * 判断文件是否为空
	 * 
	 * @param filePath
	 *            文件名（含路径）
	 * @return 文件是否存在
	 */
	public static FileState FileIsEmpty(String filePath) {
		File file = new File(filePath);
		if (file.exists()) {
			if (file.length() == 0) {
				return FileState.isEmpty;
			} else {
				return FileState.isNotEmpty;
			}
		} else {
			return FileState.isNotExists;
		}
	}

	/**
	 * 创建文件
	 * 
	 * @param filePath
	 *            文件名（含路径）
	 * @return 是否成功
	 */
	public static boolean createNewFile(String filePath) {
		File file = new File(filePath);
		if (!file.exists()) {
			try {
				return file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}
		} else {
			System.out.println(filePath + " 已存在!");
			return false;
		}
	}

	/**
	 * 删除文件或文件夹
	 * 
	 * @param filePath
	 *            文件名或文件夹名（含路径）
	 * @return 是否成功
	 */
	public static boolean deleteFileOrFolder(String filePath) {
		File file = new File(filePath);
		if (file.exists()) {
			if (file.isFile()) {
				file.delete();
				return true;
			} else if (file.isDirectory()) {
				File files[] = file.listFiles();
				for (File onefile : files) {
					deleteFileOrFolder(onefile.getAbsolutePath());
				}
			}
			file.delete();
			return true;
		} else {
			System.out.println(filePath + " 不存在!");
			return false;
		}
	}

	/**
	 * 文件重命名或者文件移动
	 * 
	 * @param filePath
	 *            文件名（含路径）
	 * @return 是否成功
	 */
	public static boolean renameOrRemoveFile(String oldFilePath,
			String newFilePath) {
		File fileSrc = new File(oldFilePath);
		File fileDest = new File(newFilePath);
		if (!fileSrc.exists()) {
			System.out.println(fileSrc + " 文件不存在!");
			return false;
		}
		return fileSrc.renameTo(fileDest);
	}

	/**
	 * 创建文件夹
	 * 
	 * @param folderPath
	 *            文件夹名称（含路径）
	 * @return 是否成功
	 */
	public static boolean createFolder(String folderPath) {
		File file = new File(folderPath);
		if (file.exists()) {
			System.out.println(folderPath + " 已存在");
			return false;
		} else {
			return file.mkdirs();
		}
	}

	/**
	 * 遍历目录中所有的文件夹和文件
	 * 
	 * @param filePath
	 *            文件（夹）路径
	 */
	public static void getFileList(String filePath) {
		File file = new File(filePath);
		if (file.exists()) {
			if (file.isFile()) {
				System.out.println("已读取: " + file.getAbsolutePath());
			} else if (file.isDirectory()) {
				File[] files = file.listFiles();
				for (File f : files) {
					getFileList(f.getAbsolutePath());
				}
			}
		} else {
			System.out.println(filePath + " 不存在");
		}
	}

	/**
	 * 获取文件大小
	 * 
	 * @param filePath
	 *            文件名
	 */
	public static void getDirSize(String filePath) {
		File file = new File(filePath);
		if (file.exists()) {
			if (file.isFile()) {
				long size = file.length();
				System.out
						.println(file.getAbsolutePath()
								+ ", 大小："
								+ (size % 1024 == 0 ? (size / 1024)
										: (size / 1024 + 1)) + "KB");
			} else if (file.isDirectory()) {
				File[] files = file.listFiles();
				for (File f : files) {
					getDirSize(f.getAbsolutePath());
				}
			}
		} else {
			System.out.println(filePath + " 不存在");
		}
	}
	
	/**
	 * 读取文本文件
	 * @param fileName 文件名
	 */
	public static void readFile(String fileName){
		FileInputStream fis = null;
		InputStreamReader isr = null;
		BufferedReader br = null;
		try {
			//创建字节输出流
			fis = new FileInputStream(fileName);
			//利用InputStreamReader包装FileInputStream字节流，并指定字节转换为字符的编码为GBK
			isr = new InputStreamReader(fis,"GBK");
			//利用BufferedReader包装InputStreamReader
			br = new BufferedReader(isr);
			String tmp = null;
			while((tmp=br.readLine())!= null){
				System.out.println(tmp);
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(br != null){
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(isr != null){
				try {
					isr.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(fis != null){
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 写文本文件
	 * @param fileName 文件名
	 * @param text 要写入的内容
	 * @param append 是否追加
	 */
	public static void writeFile(String fileName,String text,boolean append){
		FileOutputStream fos = null;
		OutputStreamWriter osr = null;
		BufferedWriter bw = null;
		File file = new File(fileName);
		if(!file.exists()){
			System.out.println(fileName+" 不存在");
			return;
		}
		try {
			//创建字节输出流
			fos = new FileOutputStream(fileName,append);
			//利用OutputStreamWriter包装FileOutputStream字节流，并指定字符转换为字节的编码为GBK
			osr = new OutputStreamWriter(fos,"GBK");
			//利用BufferedWriter包装OutputStreamWriter
			bw = new BufferedWriter(osr);
			bw.write(text);
			System.out.println("已写入文件");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(bw != null){
				try {
					bw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(osr != null){
				try {
					osr.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(fos != null){
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 读取原始字节流文件，例如图片、流媒体等。
	 * @param fileName
	 */
	public static void readStreamFile(String fileName){
		int tmp = -1;
		FileInputStream fs = null;
		BufferedInputStream bs = null;
		try {
			fs = new FileInputStream(fileName);
			bs = new BufferedInputStream(fs);
			while((tmp=bs.read())!=-1){
				System.out.print((char)tmp);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				if(bs != null){
					bs.close();
				}
				if(fs != null){
					fs.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 读取纯文本文件，例如：txt,log,csv等格式。
	 * @param fileName
	 */
	public static void readTxtFile(String fileName){
		FileReader fr = null;
		BufferedReader br = null;
		try {
			fr = new FileReader(fileName);
			br = new BufferedReader(fr); 
			String tmp = null;
			while((tmp=br.readLine())!=null){
				System.out.println(tmp);
			}

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				if(br != null){
					br.close();
				}
				if(fr != null){
					fr.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/***
	 * 文件复制
	 * @param oldPath String 原文件路径，例如：c:\a.txt
	 * @param newPath String 复制后文件路径，例如：d:\test\a.txt
	 */
	public static void copyFile(String oldPath,String newPath){
		try {
			long begin = System.currentTimeMillis();
			ByteBuffer bb = ByteBuffer.allocate(100000);
			FileInputStream fis = new FileInputStream(oldPath);
			FileChannel in = fis.getChannel();
			
			FileOutputStream fos = new FileOutputStream(newPath);
			FileChannel out = fos.getChannel();
			
			@SuppressWarnings("unused")
			int len = -1;
			while((len = in.read(bb))!=-1){
				//在write之前，将position和limit标志设置好
				bb.flip();
				//按设定的position位置开始读，到limit结束
				out.write(bb);
				//初始化position\limit\capcity标志的位置，为下一次循环读取做准备
				bb.clear();
			}
			long end = System.currentTimeMillis();
			System.out.println(end-begin);
			out.close();
			in.close();
			fos.close();
			fis.close();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 复制整个文件夹内容
	 * @param oldPath
	 * @param newPath
	 */
	public static void copyFolder(String oldPath,String newPath){
		try{
			(new File(newPath)).mkdirs(); //如果文件夹不存在则建立新文件夹
			File a = new File(oldPath);
			String[] file = a.list();
			File temp = null;
			for(int i=0;i<file.length;i++){
				if(oldPath.endsWith(File.separator)){
					temp = new File(oldPath+file[i]);
				}else{
					temp = new File(oldPath+File.separator+file[i]);
				}
				
				if(temp.isFile()){
					FileInputStream input = new FileInputStream(temp);
					FileOutputStream output = new FileOutputStream(newPath+"/"+(temp.getName()).toString());
					byte[] b = new byte[1024*5];
					int len;
					while((len = input.read(b))!=-1){
						output.write(b,0,len);
					}
					output.flush();
					output.close();
					input.close();
				}
				if(temp.isDirectory()){
					copyFolder(oldPath+"/"+file[i],newPath+"/"+file[i]);
				}
			}
			System.out.println("复制文件夹成功！");
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	/**
	 * 文件锁定功能
	 * @param filePath
	 * @param UTFcontent
	 */
	public static void lockFile(String filePath,String UTFcontent){
		RandomAccessFile raf;
		try {
			raf = new RandomAccessFile(new File(filePath),"rw");
			FileChannel fc = raf.getChannel();
			FileLock fl = fc.tryLock();
			if(fl.isValid()){
				System.out.println("文件执行读写操作！");
				raf.writeUTF(UTFcontent);
				raf.close();
				fl.release();
			}else{
				System.out.println("其他用户正在执行写入操作！");
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Convert the file to file stream.
	 * 
	 * @author peng.zhang8@gmail.com
	 * @param filePath
	 * @since 2012/9/12
	 * @return
	 */
	public static byte[] convertFileToStream(String filePath) {
		byte[] fs = null;
		try {
			FileInputStream fis = new FileInputStream(filePath);
			int size = 1024;
			ByteArrayOutputStream out = new ByteArrayOutputStream(size);
			byte[] buffer = new byte[size];
			int n;
			while ((n = fis.read(buffer)) != -1) {
				out.write(buffer, 0, n);
			}
			fis.close();
			out.close();
			fs = out.toByteArray();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return fs;
	}
	
	public static void main(String[] args) {
		// System.out.println(FileUtils.FileIsEmpty("D:\\a.txt"));
		// System.out.println(FileUtils.createNewFile("d:\\b.txt"));
		// System.out.println(FileUtils.deleteFileOrFolder("D:\\test"));
		// System.out.println(FileUtils.renameOrRemoveFile("d:\\a.txt","d:\\b.txt"));
		// System.out.println(FileUtils.createFolder("d:\\test\\log"));
		// FileUtils.getFileList("D:\\TDDOWNLOAD");
		// FileUtils.getDirSize("D:\\TDDOWNLOAD");
		//FileUtils.readFile("d:\\test.txt");
		//FileUtils.writeFile("d:\\test\\a.txt", "我是中国人",true);
		//FileUtils.readStreamFile("d:\\test\\1.png");
		//FileUtils.readTxtFile("d:\\test\\test.txt");
		//FileUtils.copyFile("c:\\a.txt", "d:\\test\\a.txt");
		//FileUtils.copyFolder("c:\\test", "d:\\test");
		FileUtils.writeFile("d:\\test\\1.xml", "<?xml version=\"1.0\" standalone=\"yes\"?>",true);
	}
}
